package com.simple.util.base;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class ChineseUtil {

	private static int serialNum = 0;// 序号

	private static String regEx = "[^0-9零一二三四五六七八九]";
	private static String regEx1 = "[^0-9]";
	/**
	 * 单位
	 */
	public static String[] CN_UNITS = new String[] { "个", "十", "百", "千", "万", "十",
			"百", "千", "亿", "十", "百", "千", "万" };
	/**
	 * 汉字
	 */
	public static String[] CN_CHARS = new String[] { "零", "一", "二", "三", "四",
			"五", "六", "七", "八", "九" };
	public final static char[] ARABIC_NUMBER_ARRAY = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
	public final static char[] CHINESE_NUMBER_ARRAY = { '零', '一', '二', '三', '四', '五', '六', '七', '八', '九' };
	
	/**
	 * 排序
	 * 
	 * @param list
	 */
	public static Map<String, Integer> sort(int groupCount, List<String> list) {
		if (CollectionUtils.isEmpty(list)) {
			return null;
		}
		serialNum = groupCount;
		Map<String, List<String>> classMap = new HashMap<String, List<String>>();
		char key = 'a';
		for (String u : list) {
			key = 'a';
			for (char c : CHINESE_NUMBER_ARRAY) {
				// 如果存在汉字
				if (u.indexOf(c) >= 0) {
					if (u.indexOf(c) < u.length()) {
						for (char a : ARABIC_NUMBER_ARRAY) {
							if (u.substring(u.indexOf(c), u.length()).indexOf(a) > 0) {
								// 汉字后面是否有数字
								key = 'b';
								break;
							} else if (u.substring(0, u.indexOf(c)).indexOf(a) > 0) {
								// 汉字前面是否有数字
								key = 'c';
								break;
							}
						}
					}
					if (key == 'a') {
						// 仅有汉字
						key = 'd';
						break;
					}
				}
			}
			if (key == 'a') {
				// 仅数字
				for (char c : ARABIC_NUMBER_ARRAY) {
					if (u.contains(String.valueOf(c))) {
						key = 'e';
						break;
					}
				}
			}
			if (CollectionUtils.isEmpty(classMap.get(String.valueOf(key)))) {
				classMap.put(String.valueOf(key), new ArrayList<String>());
			}
			classMap.get(String.valueOf(key)).add(u);
		}
		Map<String, Integer> sortResultMap = new HashMap<String, Integer>();
		for (Object element : sortLetterMapKey(classMap)) {
			String kset = (String) element;
			for (Entry<String, List<String>> entry : classMap.entrySet()) {
				if (kset.equals(entry.getKey())) {
					dealNameSort(entry.getKey(), entry.getValue(), sortResultMap);
				}
			}
		}
		return sortResultMap;
	}

	/**
	 * 处理名称排序
	 *
	 * @param type
	 * @param list
	 */
	private static void dealNameSort(String type, List<String> list, Map<String, Integer> sortResultMap) {
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		switch (type) {
		case "a":
			dealATypeSort(list, sortResultMap);
			break;
		case "b":
			dealBTypeSort(list, sortResultMap);
			break;
		case "c":
			dealCTypeSort(list, sortResultMap);
			break;
		case "d":
			dealDTypeSort(list, sortResultMap);
			break;
		case "e":
			dealETypeSort(list, sortResultMap);
			break;
		default:
			break;
		}
	}

	/**
	 * 排序数字key
	 *
	 * @param map
	 * @return
	 */
	private static List<Integer> sortNumberMapKey(Map<Integer, ?> map) {
		List<Integer> alist = new ArrayList<Integer>(map.keySet());
		Collections.sort(alist);
		return alist;
	}

	/**
	 * 排序字母key
	 *
	 * @param map
	 * @return
	 */
	private static List<String> sortLetterMapKey(Map<String, ?> map) {
		List<String> alist = new ArrayList<String>(map.keySet());
		Collections.sort(alist, new Comparator<Object>() {
			@Override
			public int compare(Object a, Object b) {
				return a.toString().toLowerCase().compareTo(b.toString().toLowerCase());
			}
		});
		return alist;
	}

	/**
	 * 排序value
	 *
	 * @param sortResultMap
	 * @return
	 */
	private static Map<String, Integer> sortMapValue(Map<String, Integer> sortResultMap) {
		List<Entry<String, Integer>> keys = new ArrayList<Entry<String, Integer>>(sortResultMap.entrySet());
		Collections.sort(keys, new Comparator<Entry<String, Integer>>() {
			@Override
			public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
				return (o1.getValue() - o2.getValue());
			}
		});
		Map<String, Integer> newMap = new LinkedHashMap<String, Integer>();
		for (int i = 0; i < keys.size(); i++) {
			newMap.put(keys.get(i).getKey(), keys.get(i).getValue());
		}
		return newMap;
	}

	/**
	 * 处理中文类型
	 *
	 * @param list
	 * @return
	 */
	private static Map<Integer, List<String>> dealChineseType(List<String> list) {
		if (CollectionUtils.isEmpty(list)) {
			return null;
		}
		Map<Integer, List<String>> map = new HashMap<Integer, List<String>>();
		StringBuffer sb = null;
		for (String obj : list) {
			sb = new StringBuffer();
			for (int i = 0; i < obj.length(); i++) {
				for (int k = 0; k < CHINESE_NUMBER_ARRAY.length; k++) {
					if (obj.charAt(i) == CHINESE_NUMBER_ARRAY[k]) {
						sb.append(ARABIC_NUMBER_ARRAY[k]);
					}
				}
			}
			Integer key = Integer.parseInt(sb.toString());
			if (!map.containsKey(key)) {
				map.put(key, new ArrayList<String>());
			}
			map.get(key).add(obj);
		}
		return map;
	}

	/**
	 * 处理数字类型
	 *
	 * @param list
	 * @return
	 */
	private static Map<Integer, List<String>> dealArabicNumberType(List<String> list) {
		if (CollectionUtils.isEmpty(list)) {
			return null;
		}
		Map<Integer, List<String>> map = new HashMap<Integer, List<String>>();
		StringBuffer sb = null;
		for (String obj : list) {
			sb = new StringBuffer();
			for (int i = 0; i < obj.length(); i++) {
				for (char element : ARABIC_NUMBER_ARRAY) {
					if (obj.charAt(i) == element) {
						sb.append(element);
					}
				}
			}
			Integer key = Integer.parseInt(sb.toString());
			if (!map.containsKey(key)) {
				map.put(key, new ArrayList<String>());
			}
			map.get(key).add(obj);
		}
		return map;
	}

	/**
	 * 处理A类型排序
	 *
	 * @param list
	 */
	private static void dealATypeSort(List<String> list, Map<String, Integer> sortResultMap) {
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		for (String key : list) {
			if (!sortResultMap.containsKey(key)) {
				sortResultMap.put(key, ++serialNum);
			}
		}
	}

	/**
	 * 处理B类型排序
	 *
	 * @param list
	 */
	private static void dealBTypeSort(List<String> list, Map<String, Integer> sortResultMap) {
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		Map<Integer, List<String>> map = dealChineseType(list);
		for (Object element : sortNumberMapKey(map)) {
			Integer kset = (Integer) element;
			for (Entry<Integer, List<String>> entry : map.entrySet()) {
				if (kset.equals(entry.getKey())) {
					dealETypeSort(entry.getValue(), sortResultMap);
				}
			}
		}
	}

	/**
	 * 处理C类型排序
	 *
	 * @param list
	 */
	private static void dealCTypeSort(List<String> list, Map<String, Integer> sortResultMap) {
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		Map<Integer, List<String>> map = dealArabicNumberType(list);
		for (Object element : sortNumberMapKey(map)) {
			Integer kset = (Integer) element;
			for (Entry<Integer, List<String>> entry : map.entrySet()) {
				if (kset.equals(entry.getKey())) {
					dealDTypeSort(entry.getValue(), sortResultMap);
				}
			}
		}
	}

	/**
	 * 处理D类型排序
	 *
	 * @param list
	 */
	private static void dealDTypeSort(List<String> list, Map<String, Integer> sortResultMap) {
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		Map<Integer, List<String>> map = dealChineseType(list);
		for (Object element : sortNumberMapKey(map)) {
			Integer kset = (Integer) element;
			for (Entry<Integer, List<String>> entry : map.entrySet()) {
				if (kset.equals(entry.getKey())) {
					for (String k : entry.getValue()) {
						sortResultMap.put(k, ++serialNum);
					}
				}
			}
		}
	}

	/**
	 * 处理E类型排序
	 *
	 * @param list
	 */
	private static void dealETypeSort(List<String> list, Map<String, Integer> sortResultMap) {
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		Map<Integer, List<String>> map = dealArabicNumberType(list);
		for (Object element : sortNumberMapKey(map)) {
			Integer kset = (Integer) element;
			for (Entry<Integer, List<String>> entry : map.entrySet()) {
				if (kset.equals(entry.getKey())) {
					for (String k : entry.getValue()) {
						sortResultMap.put(k, ++serialNum);
					}
				}
			}
		}
	}

	/**
	 * @param chinese
	 * @return
	 */
	public static Integer fetchNum(String chinese) {
		try {
			String str = StringUtils.replacePattern(chinese, regEx, "");
			Matcher m = Pattern.compile(regEx1).matcher(str);
			while (m.find()) {
				str = StringUtils.replace(str, m.group(), chinese2Num(m.group()));
			}
			return StringUtils.isBlank(str) ? 0 : Integer.valueOf(str);
		}catch(Exception e){
			return 1000;
		}
	}

	private static String chinese2Num(String str) {
		String num = "0";
		switch (str) {
		case "一":
			num = "1";
			break;
		case "二":
			num = "2";
			break;
		case "三":
			num = "3";
			break;
		case "四":
			num = "4";
			break;
		case "五":
			num = "5";
			break;
		case "六":
			num = "6";
			break;
		case "七":
			num = "7";
			break;
		case "八":
			num = "8";
			break;
		case "九":
			num = "9";
			break;
		}
		return num;
	}


	/**
	 * 数字转中文
	 */
	public static String number2Chinese(long num) {
		return String.join("", numberToChinesAsArray(num));
	}

	/**
	 * 数字转中文返回字符数组
	 */
	public static String[] numberToChinesAsArray(long num) {
		if (num < 10) {// 10以下直接返回对应汉字
			return new String[] { CN_CHARS[(int) num] };// ASCII2int
		}

		char[] chars = String.valueOf(num).toCharArray();
		if (chars.length > CN_UNITS.length) {// 超过单位表示范围的返回空
			return new String[] {};
		}

		boolean isLastUnitStep = false;// 记录上次单位进位
		ArrayList<String> cnchars = new ArrayList<String>(chars.length * 2);// 创建数组，将数字填入单位对应的位置
		for (int pos = chars.length - 1; pos >= 0; pos--) {// 从低位向高位循环
			char ch = chars[pos];
			String cnChar = CN_CHARS[ch - '0'];// ascii2int 汉字
			int unitPos = chars.length - pos - 1;// 对应的单位坐标
			String cnUnit = CN_UNITS[unitPos];// 单位
			boolean isZero = (ch == '0');// 是否为0
			boolean isZeroLow = (pos + 1 < chars.length && chars[pos + 1] == '0');// 是否低位为0

			boolean isUnitStep = (unitPos >= 4 && (unitPos % 4 == 0));// 当前位是否需要单位进位

			if (isUnitStep && isLastUnitStep) {// 去除相邻的上一个单位进位
				int size = cnchars.size();
				cnchars.remove(size - 1);
				if (!CN_CHARS[0].equals(cnchars.get(size - 2))) {// 补0
					cnchars.add(CN_CHARS[0]);
				}
			}

			if (isUnitStep || !isZero) {// 单位进位(万、亿)，或者非0时加上单位
				cnchars.add(cnUnit);
				isLastUnitStep = isUnitStep;
			}
			if (isZero && (isZeroLow || isUnitStep)) {// 当前位为0低位为0，或者当前位为0并且为单位进位时进行省略
				continue;
			}
			cnchars.add(cnChar);
			isLastUnitStep = false;
		}

		Collections.reverse(cnchars);
		// 清除最后一位的0
		int chSize = cnchars.size();
		String chEnd = cnchars.get(chSize - 1);
		if (CN_CHARS[0].equals(chEnd) || CN_UNITS[0].equals(chEnd)) {
			cnchars.remove(chSize - 1);
		}

		// 口语化处理
		String chFirst = cnchars.get(0);
		String chSecond = cnchars.get(1);
		if (chFirst.equals(CN_CHARS[1]) && chSecond.startsWith(CN_UNITS[1])) {// 是否以'一'开头，紧跟'十'
			cnchars.remove(0);
		}
		return cnchars.toArray(new String[] {});
	}
}
